home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gscript / gs261s.zoo / atari / gdevvdi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-25  |  27.5 KB  |  1,184 lines

  1. /* Copyright (C) 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gdevvdi.c */
  21.  
  22. /* Bitmapped screen device for the Atari ST. This driver contains
  23.  * portions of code originally written by Hauke Hess. It uses the
  24.  * vdi for all screen operations. It recognizes and supports 1, 2,
  25.  * 4, 8, and 16 bit color. Tim Gallivan 9/93.
  26.  */
  27.  
  28. /* For monochrome, Ghostscript produces a bitmap in memory which
  29.  * is referenced directly by 'base'. For color images, GS produces
  30.  * a bitmap at 'base' with each pixel represented by several
  31.  * consecutive bits (packed or chunky pixel format). The routine
  32.  * 'pack_to_plane()' copies the GS "packed" image format into the
  33.  * appropriate number of color planes, referenced by 'cbase'. The
  34.  * image in 'cbase' is then copied back to 'base' with the vdi routine
  35.  * 'vr_trnfm()', and is then copied to the screen. This is rather
  36.  * convoluted, but is needed for portability.
  37.  */
  38.  
  39. #include "gdevvdi.h"
  40.  
  41. /* Variables imported from gp_atari.c */
  42.  
  43. extern gx_color_value MaxRGB;
  44. extern short Chunky8, Chunky16;
  45. extern short Gdebug, Debug8, Debug16;
  46. extern short TrueColor;
  47. extern int *Palette;
  48. extern uint PaletteSize;
  49. extern int *ColorReg;
  50. extern int XRes, YRes, ColorBits;
  51. extern int msgbuff[], pxy[];
  52. extern int VdiHandle;
  53. extern int window;
  54. extern float AspectRatio;
  55.  
  56. extern WINDOW imag;
  57. extern GRECT full;
  58. extern MFDB plane_image, image, screen;
  59.  
  60. /* General screen driver variables. */
  61.  
  62. /* lineptr is an array of pointers to the beginning of each scan
  63.  *     line in the GS bitmap.
  64.  */
  65.  
  66. byte *cbase=0, **lineptr;
  67. ushort *plane[16], *tbase;
  68.  
  69. uint csize;
  70.  
  71. int ColorIndex=2, words;
  72.  
  73. int width, height, byte_width, word_width, raster;
  74. int plot_x, plot_y, step_dx, step_dy;
  75. int copy_width, copy_height;
  76.  
  77. /* Global Ghostscript variables. */
  78.  
  79. ulong mem_space;
  80.  
  81. private dev_proc_open_device(stvdi_open);
  82. private dev_proc_close_device(stvdi_close);
  83. private dev_proc_output_page(stvdi_output_page);
  84. private dev_proc_print_page(stvdi_print_page);
  85. private dev_proc_map_rgb_color(stvdi_map_rgb_color);
  86. private dev_proc_map_color_rgb(stvdi_map_color_rgb);
  87.  
  88. private gx_device_procs stvdi_procs =
  89.   prn_color_procs(stvdi_open, stvdi_output_page, stvdi_close,
  90.     stvdi_map_rgb_color, stvdi_map_color_rgb);
  91.  
  92. gx_device_printer gs_stvdi_device =
  93.   prn_device(stvdi_procs, "stvdi",
  94.     WIDTH_10THS, HEIGHT_10THS,
  95.     X_DPI, Y_DPI,
  96.     0,0,0,0,            /* margins */
  97.     1, stvdi_print_page);        /* default to monochrome */
  98.  
  99. /* Open the stvdi device--get the resolution, allocate memory, etc. */
  100.  
  101. int
  102. stvdi_open(gx_device *pdev)
  103. {
  104.     byte *base=0;
  105.     const gx_device_memory *mdev;
  106.     gx_device_procs *pprocs = pdev->procs;
  107.  
  108.     int ret;
  109.  
  110.     if (Gdebug) eprintf("stvdi_open ...");
  111.  
  112.     pdev->y_pixels_per_inch = 
  113.                (int)(AspectRatio * pdev->y_pixels_per_inch + .5);
  114.     pdev->height = (int)(AspectRatio * pdev->height + .5);
  115.  
  116.     /* Get an appropriate memory device. */
  117.  
  118.     if ((mdev = gdev_mem_device_for_bits(ColorBits)) == 0)
  119.         return_error(gs_error_rangecheck);
  120.  
  121.     width = pmemdev->width;        /* width in pixels */
  122.     height = pmemdev->height;    /* height in pixels */
  123.  
  124.     byte_width = (width + 7) >> 3;        /* pixel width / 8 */
  125.     word_width = (byte_width + 1) >> 1;    /* pixel width / 16 */
  126.  
  127.     /* Ensure that the width is a multiple of 16 pixels. */
  128.  
  129.     pmemdev->width = 16 * word_width;
  130.  
  131.     if (window) {
  132.  
  133.         wind_calc(0, imag.gadgets,
  134.         imag.canvas.g_x, imag.canvas.g_y, width, height,
  135.         &imag.mframe.g_x, &imag.mframe.g_y,
  136.         &imag.mframe.g_w, &imag.mframe.g_h);
  137.  
  138.         imag.oframe.g_x = 0; imag.oframe.g_y = 0;
  139.         imag.oframe.g_w = 0; imag.oframe.g_h = 0;
  140.  
  141.     }
  142.  
  143.     if (ColorBits > 1) {
  144.  
  145.         /* Fill the color_info structure. */
  146.  
  147.         ppdev->color_info.num_components = 3;
  148.         ppdev->color_info.depth       = mdev->color_info.depth;
  149.         ppdev->color_info.max_gray    = PaletteSize/3 - 1;
  150.         ppdev->color_info.max_rgb     = MaxRGB;
  151.         ppdev->color_info.dither_gray = DITH_GRAY(ColorBits);
  152.         ppdev->color_info.dither_rgb  = DITH_RGB(ColorBits);
  153.  
  154.         if (Gdebug) {
  155.         eprintf1("Depth    = %ld\n", ppdev->color_info.depth);
  156.         eprintf1("Max Gray = %ld\n", ppdev->color_info.max_gray);
  157.         eprintf1("Max RGB  = %ld\n", ppdev->color_info.max_rgb);
  158.         eprintf1("Dither Gray = %ld\n", ppdev->color_info.dither_gray);
  159.         eprintf1("Dither RGB  = %ld\n", ppdev->color_info.dither_rgb);
  160.         }
  161.  
  162.     }
  163.  
  164.     memset(ppdev->skip, 0, sizeof(ppdev->skip));
  165.     ppdev->orig_procs = pprocs;
  166.     ppdev->page_count = 0;
  167.     ppdev->file = ppdev->ccfile = ppdev->cbfile = NULL;
  168.     mem_space = gdev_mem_bitmap_size(pmemdev);
  169.  
  170.     /* Base points to a buffer that GS uses to construct the image. */
  171.  
  172.     if ( mem_space != (uint)mem_space   ||    /* too big to allocate */
  173.        (base = (byte *)gs_malloc((uint)mem_space, 1, "printer buffer"))
  174.         == 0    /* can't allocate */
  175.        ) {
  176.         eprintf("stvdi_open: Malloc for printer buffer failed.\n");
  177.         return_error(gs_error_VMerror);
  178.     }
  179.  
  180.     /* Cbase points to a buffer that holds the standard GEM
  181.      * color plane image.
  182.      */
  183.  
  184.     if ((ColorBits > 1) && !Chunky8 && !Chunky16) {
  185.  
  186.         csize = (uint)(2 * word_width * height * ColorBits);
  187.  
  188.         if ((cbase = (byte *)gs_malloc(csize, 1, "color buffer")) == 0) {
  189.         eprintf("stvdi_open: Malloc for color buffer failed.\n");
  190.         return_error(gs_error_VMerror);
  191.         }
  192.  
  193.     }
  194.  
  195.        /* Render entirely in memory. */
  196.  
  197.     ppdev->buffer_space = 0;
  198.     pmemdev->base = base;
  199.     ppdev->mod_procs = *mdev->procs;
  200.  
  201.     /* Synthesize the procedure vector. */
  202.     /* Rendering operations come from the memory device, */
  203.     /* non-rendering come from the printer device. */
  204.  
  205.     pdev->procs = &ppdev->mod_procs;
  206.  
  207. #define copy_proc(p) ppdev->mod_procs.p = pprocs->p
  208.     copy_proc(get_initial_matrix);
  209.     copy_proc(output_page);
  210.     copy_proc(close_device);
  211.     copy_proc(map_rgb_color);
  212.     copy_proc(map_color_rgb);
  213.     copy_proc(get_props);
  214.     copy_proc(put_props);
  215.     copy_proc(map_cmyk_color);
  216.     copy_proc(get_xfont_procs);
  217.     copy_proc(get_xfont_device);
  218. #undef copy_proc
  219.  
  220.     /* Open the memory device. */
  221.  
  222.     if ((ret = (*pdev->procs->open_device)(pdev)) != 0) {
  223.         return ret;
  224.     }
  225.  
  226.     raster = pmemdev->raster;
  227.  
  228.     /* Set up the MFDBs for the GS image and the screen. */
  229.  
  230.     screen.fd_addr   = (long)NULL;
  231.  
  232.     image.fd_addr    = (long)base;
  233.     image.fd_w       = (ColorBits > 1) ? 16 * word_width: 8 * raster;
  234.     image.fd_h       = height;
  235.     image.fd_wdwidth = image.fd_w/16;
  236.     image.fd_stand   = 0;
  237.     image.fd_nplanes = ColorBits;
  238.  
  239.     if (ColorBits > 1 && cbase) {
  240.  
  241.         /* Set up the MFDB for the color image buffer. */
  242.  
  243.         plane_image.fd_addr    = (long)cbase;
  244.         plane_image.fd_w       = 16 * word_width;
  245.         plane_image.fd_h       = height;
  246.         plane_image.fd_wdwidth = image.fd_w/16;
  247.         plane_image.fd_stand   = 1;
  248.         plane_image.fd_nplanes = ColorBits;
  249.  
  250.     }
  251.  
  252.     return 0;
  253. }
  254.  
  255. /* Close the stvdi device--free memory, close workstations, etc. */
  256.  
  257. int
  258. stvdi_close(gx_device *pdev)
  259. {
  260.  
  261.     if (Gdebug) eprintf("stvdi_close ...");
  262.  
  263.     /* Close the window. */
  264.  
  265.     if (imag.opened) {
  266.         if (Gdebug) eprintf("closing win in stvdi close");
  267.         wind_close(imag.handle);
  268.         imag.opened = 0;
  269.     }
  270.  
  271.     /* Free the memory device bitmap. */
  272.  
  273.     gs_free((char *)pmemdev->base, (uint)gdev_mem_bitmap_size(pmemdev),
  274.         1, "printer buffer");
  275.  
  276.     /* Free the memory for the color image buffer. */
  277.  
  278.     if (ColorBits > 1 && cbase) {
  279.         gs_free((char *)cbase, csize, 1, "color buffer");
  280.     }
  281.  
  282.     pdev->procs = ppdev->orig_procs;
  283.  
  284.     return 0;
  285. }
  286.  
  287. int
  288. stvdi_output_page(gx_device *pdev, int num_copies, int flush)
  289. {    int code;
  290.  
  291.     ppdev->page_count++;
  292.  
  293.     /* print the accumulated page description */
  294.     code = (*ppdev->print_page)(ppdev, ppdev->file);
  295.  
  296.     ColorIndex = 2;       /* indices > 2 available for new colors. */
  297.  
  298.     if ( code < 0 ) return code;
  299.     return 0;
  300. }
  301.  
  302. /* Print the bitmap for the current page to the screen. */
  303.  
  304. private int
  305. stvdi_print_page(gx_device_printer *pdev, FILE *dummy)
  306. {
  307.     byte *base;
  308.  
  309.     int count, show_end, pad, length, top, empty;
  310.  
  311.     long ch;
  312.  
  313.     show_end = 0;
  314.  
  315.     /* Calculate the number of padding bits in the last byte. */
  316.  
  317.     pad = (8 * byte_width - width) * ColorBits;
  318.     length = byte_width * ColorBits;
  319.  
  320.     plot_x = 0;
  321.     plot_y = 0;
  322.  
  323.     lineptr = pmemdev->line_ptrs;
  324.     base = *lineptr;
  325.     tbase = (ushort *)base;    /* accessed from assembly routines */
  326.  
  327.     /* Find the first line containing nonzero bits. */
  328.  
  329.     while (plot_y < height) {
  330.  
  331.         /* Search the scanline for a nonzero bit. */
  332.  
  333.         for (count=0; (count < length)
  334.                  && (base[count] == 0); ++count) ;
  335.  
  336.         if (count >= length) {    /* Empty line, continue. */
  337.         plot_y++;
  338.         base = lineptr[plot_y];
  339.         }
  340.         else if ((count==length-1) && (base[count]>>pad == 0)) {
  341.         plot_y++;    /* nonzero bits in padding, continue */
  342.         base = lineptr[plot_y];
  343.         }
  344.         else {        /* Nonzero bits found, break loop. */
  345.         plot_y--;
  346.         break;
  347.         }
  348.     }
  349.  
  350.     /* Convert the packed image to standard GEM color planes,
  351.      * then convert the plane image to the final platform-dependent
  352.      * screen format. If the platform-dependent format is chunky,
  353.      * then do nothing.
  354.      */
  355.  
  356.     if (ColorBits == 16 && Chunky16) {
  357.         ;
  358.     }
  359.     else if (ColorBits == 8 && Chunky8) {
  360.         ;
  361.     }
  362.     else {
  363.         stvdi_pack_to_plane();
  364.         vr_trnfm(VdiHandle, &plane_image, &image);
  365.     }
  366.  
  367.     /* Open a window if necessary. */
  368.  
  369.     if (window) {
  370.  
  371.         graf_mouse(M_OFF, 0L );
  372.  
  373.         if (imag.oframe.g_w && imag.oframe.g_w) {
  374.  
  375.         if (imag.opened) {
  376.  
  377.             msgbuff[3] = imag.handle;
  378.             gp_win_redraw(FULL_WIN);
  379.  
  380. #if 0
  381.             wind_get(0, WF_TOP, &top, &empty,
  382.                           &empty, &empty);
  383.  
  384.             if (top == imag.handle) {
  385.             msgbuff[3] = imag.handle;
  386.             gp_win_redraw(FULL_WIN);
  387.             }
  388.             else {
  389.             wind_set(imag.handle, WF_TOP, 0, 0, 0, 0);
  390.             }
  391. #endif
  392.  
  393.         }
  394.         else {
  395.  
  396.             wind_open(imag.handle,
  397.             imag.oframe.g_x, imag.oframe.g_y,
  398.             MIN(imag.mframe.g_w, imag.oframe.g_w),
  399.             MIN(imag.mframe.g_h, imag.oframe.g_h));
  400.  
  401.         }
  402.  
  403.         }
  404.         else if (!imag.opened) {
  405.  
  406.         wind_open(imag.handle,
  407.             full.g_x, full.g_y,
  408.             MIN(imag.mframe.g_w, full.g_w),
  409.             MIN(imag.mframe.g_h, full.g_h));
  410.  
  411.         wind_get(imag.handle, WF_CURRXYWH,
  412.             &imag.oframe.g_x, &imag.oframe.g_y,
  413.                 &imag.oframe.g_w, &imag.oframe.g_h);
  414.  
  415.         wind_get(imag.handle, WF_WORKXYWH,
  416.             &imag.canvas.g_x, &imag.canvas.g_y,
  417.             &imag.canvas.g_w, &imag.canvas.g_h);
  418.  
  419.         }
  420.  
  421.         update_scroll(imag.handle);
  422.         imag.opened = 1;
  423.  
  424.         graf_mouse(BUSY_BEE, 0L);
  425.         graf_mouse(M_ON, 0L);
  426.  
  427.     }
  428.     else {
  429.  
  430.         copy_width  = MIN(XRes, width-1);    /* in pixels */
  431.         copy_height = MIN(YRes, height-1);    /* in pixels */
  432.         step_dx = .9 * copy_width;
  433.         step_dy = .9 * copy_height;
  434.  
  435.         if (plot_y < 0)
  436.         plot_y = 0;
  437.  
  438.         if (plot_y >= height - copy_height)
  439.         plot_y = (height - 1) - copy_height;
  440.  
  441.         v_exit_cur(VdiHandle);
  442.  
  443.     }
  444.  
  445.     if (Debug8 || Debug16) {
  446.         dprintf1("%s\n", "Done!");
  447.         getchar();
  448.         return 0;
  449.     }
  450.  
  451.     while (!show_end && !window) {
  452.  
  453.         pxy[0] = plot_x;
  454.         pxy[1] = plot_y;
  455.         pxy[2] = pxy[0] + copy_width;
  456.         pxy[3] = pxy[1] + copy_height;
  457.         pxy[4] = 0;
  458.         pxy[5] = 0;
  459.         pxy[6] = pxy[4] + copy_width;
  460.         pxy[7] = pxy[5] + copy_height;
  461.  
  462.         graf_mouse(M_OFF, 0L );
  463.         vs_clip(VdiHandle, 1, &pxy[4]);
  464.         wind_update(BEG_UPDATE);    /* lock the screen */
  465.  
  466.         vro_cpyfm(VdiHandle, 3, pxy, &image, &screen);
  467.  
  468.         wind_update(END_UPDATE);    /* release screen */
  469.         vs_clip(VdiHandle, 0, &pxy[4]);
  470.         graf_mouse(ARROW, 0L );
  471.         graf_mouse(M_ON, 0L );
  472.  
  473.         /* Accept keyboard commands to manipulate the screen image. */
  474.  
  475.         ch = (Bconin(2) >> 16) & 255;    /* Get key scancode */
  476.         
  477.         switch(ch) {
  478.  
  479.         case 16:            /* Q */
  480.         show_end = 1;
  481.         break;
  482.  
  483.         case 71:            /* Clr/Home */
  484.         step_dx /= 2; step_dy /= 2;
  485.         if (step_dx < 2) step_dx = 1;
  486.         if (step_dy < 2) step_dy = 1;
  487.         break;
  488.  
  489.         case 72:            /* Up cursor */
  490.         plot_y = MAX(plot_y - step_dy, 0);
  491.         break;
  492.  
  493.         case 75:            /* Left cursor */
  494.         plot_x = MAX(plot_x - step_dx, 0);
  495.         break;
  496.  
  497.         case 77:            /* Right cursor */
  498.         plot_x = plot_x + step_dx;
  499.         if (plot_x >= width - copy_width)
  500.             plot_x = (width - 1) - copy_width;
  501.         if (plot_x < 0) plot_x = 0;
  502.         break;
  503.  
  504.         case 80:            /* Down cursor */
  505.         plot_y = plot_y + step_dy;
  506.         if (plot_y >= height - copy_height)
  507.             plot_y = (height - 1) - copy_height;
  508.         if (plot_y < 0) plot_y = 0;
  509.         break;
  510.  
  511.         case 82:            /* Insert */
  512.         step_dx *= 2; step_dy *= 2;
  513.         if (step_dx > copy_width)  step_dx = copy_width;
  514.         if (step_dy > copy_height) step_dy = copy_height;
  515.         break;
  516.  
  517.         case 97:            /* Undo */
  518.         plot_x = 0;
  519.         plot_y = 0;
  520.         break;
  521.  
  522.         case 98:            /* Help */
  523.         stvdi_DisplayHelp();
  524.         Bconin(2);
  525.         stvdi_clear_screen(0);
  526.         break;
  527.             
  528.         }
  529.  
  530.     }
  531.  
  532.     if (!window) {
  533.         v_enter_cur(VdiHandle);
  534.     }
  535.  
  536.     return (0);
  537.  
  538. }
  539.  
  540. int stvdi_DisplayHelp()
  541. {
  542.     dprintf2("%c%c Help for GhostScript Screen Driver\n", 27, 'E');
  543.     dprintf(" Original Code by Hauke Hess.\n\n");
  544.     dprintf(" Q:            Quit this page (to next page or GS prompt).\n");
  545.     dprintf(" Cursor Keys:  Scroll screen in direction of cursor.\n");
  546.     dprintf(" Help:         Display help screen.\n");
  547.     dprintf(" Undo:         Move to upper-left corner of page.\n");
  548.     dprintf(" Insert:       Multiply scroll incrememt by 2.\n");
  549.     dprintf(" Clr/Home:     Divide scroll increment by 2.\n");
  550.     dprintf("\n Command line option -r<XDPI>x<YDPI> sets resolution.\n");
  551.  
  552. #if 0
  553.     dprintf("\n Helpseite des GhostScript Previewers no(c)\n");
  554.     dprintf(" Hauke Heß 1991\n");
  555.     dprintf(" Cursortasten: bewegen in entsprechender Richtung\n");
  556.     dprintf(" Undo:         Zurück nach links oben auf der Seite\n");
  557.     dprintf(" Insert:       Schrittweiter vergrößern\n");
  558.     dprintf(" Clr/Home:     Schrittweite verkleinern\n");
  559.     dprintf("\n Kommandozeilenparameter -r<XDPI>x<YDPI> setzt die Auflösung\n");
  560. #endif
  561.  
  562.     dprintf("\n >> Hit any key to continue. <<");
  563.  
  564.     return(0);
  565. }
  566.  
  567. int
  568. stvdi_clear_screen(int cursor)
  569. {
  570.     if (cursor) {
  571.         v_enter_cur(VdiHandle);
  572.     }
  573.     else {
  574.         v_exit_cur(VdiHandle);
  575.     }
  576. }
  577.  
  578.  
  579. /* Map a r-g-b color to a color index. */
  580.  
  581. /* Ghostscript asks this routine which color index should be associated
  582.  * with a given RGB triplet. I try to make the most of a limited number
  583.  * of colors by setting the palette dynamically as GS requests colors.
  584.  * Black and white, however, always reside at color indices 1 and 0.
  585.  * When the palette is full and a new color is requested, the closest
  586.  * color in the palette is returned.
  587.  */
  588.  
  589. #define BK    0
  590. #define WT    3000
  591.  
  592. gx_color_index
  593. stvdi_map_rgb_color(gx_device *pdev, gx_color_value r, gx_color_value g,
  594.   gx_color_value b) {
  595.  
  596.     register int *pptr = Palette;
  597.     register int diff;
  598.  
  599.     int *pptr2 = Palette;
  600.     static int BlackSet=0, WhiteSet=0;
  601.  
  602.     int rgb[3], red, grn, blu;
  603.     int *which, tindex, best = 1000*3, psize = PaletteSize/3;
  604.  
  605.     float max_value = (float)gx_max_color_value;
  606.  
  607.     if (TrueColor) {
  608.         tindex = psize;
  609.     }
  610.     else {
  611.         tindex = ColorIndex;
  612.     }
  613.  
  614.     if (ColorBits == 1) {        /* monochrome */
  615.       return ((r | g | b) > gx_max_color_value / 2 ?
  616.             (gx_color_index)0 : (gx_color_index)1);
  617.     }
  618.  
  619.     /* Change GS rgb values to ST vdi rgb values. */
  620.  
  621.     red = rgb[0] = 1000 * ((float)r / max_value);
  622.     grn = rgb[1] = 1000 * ((float)g / max_value);
  623.     blu = rgb[2] = 1000 * ((float)b / max_value);
  624.  
  625.     switch (red + grn + blu) {
  626.  
  627.     case WT:    /* white -- keep at vdi index 0 */
  628.         if (!TrueColor) {
  629.         if (!WhiteSet) {
  630.             Palette[0] = rgb[0];
  631.             Palette[1] = rgb[1];
  632.             Palette[2] = rgb[2];
  633.             vs_color(VdiHandle, 0, rgb);
  634.             WhiteSet = 1;
  635.         }
  636.         return (gx_color_index)ColorReg[0];
  637.         }
  638.  
  639.     case BK:    /* black -- keep at vdi index 1 */
  640.         if (!TrueColor) {
  641.         if (!BlackSet) {
  642.             Palette[3] = rgb[0];
  643.             Palette[4] = rgb[1];
  644.             Palette[5] = rgb[2];
  645.             vs_color(VdiHandle, 1, rgb);
  646.             BlackSet = 1;
  647.         }
  648.         return (gx_color_index)ColorReg[1];
  649.         }
  650.  
  651.     default:    /* search the palette for the requested color */
  652.         while ( tindex-- > 0 ) {
  653.         diff = *pptr - red;
  654.         if ( diff < 0 ) diff = -diff;
  655.  
  656.         if ( diff < best ) {    /* quick rejection */
  657.             int dg = pptr[1] - grn;
  658.             if ( dg < 0 ) dg = -dg;
  659.  
  660.             if ( (diff += dg) < best ) {    /* quick rejection */
  661.             int db = pptr[2] - blu;
  662.             if ( db < 0 ) db = -db;
  663.  
  664.             if ( (diff += db) < best )
  665.                 which = pptr, best = diff;
  666.                 if (best == 0) break;
  667.             }
  668.  
  669.         }
  670.         pptr += 3;
  671.         }
  672.  
  673.         /* If a color register is available, set it,
  674.          * if not, return the nearest color match.
  675.          */
  676.  
  677.         if (best == 0 || ColorIndex >= psize || TrueColor) {
  678.         return (gx_color_index)ColorReg[(which - Palette)/3];
  679.         }
  680.         else {
  681.         int i;
  682.  
  683.         if (ColorIndex == 3 && ColorBits > 2) ColorIndex++;
  684.         i = 3 * ColorIndex;
  685.  
  686.         Palette[i]   = rgb[0];
  687.         Palette[i+1] = rgb[1];
  688.         Palette[i+2] = rgb[2];
  689.  
  690.         vs_color(VdiHandle, ColorIndex, rgb);
  691.  
  692.         return (gx_color_index)ColorReg[ColorIndex++];
  693.         }
  694.  
  695.         break;
  696.  
  697.     }
  698. }
  699.  
  700. /* Map a color index to a r-g-b color. */
  701. int
  702. stvdi_map_color_rgb(gx_device *pdev, gx_color_index color,
  703.   gx_color_value prgb[3])
  704. {
  705.     int *pptr;
  706.     int max_value = gx_max_color_value;
  707.  
  708.     if (ColorBits == 1) {        /* monochrome */
  709.       return gdev_prn_map_color_rgb(pdev, color, prgb);
  710.     }
  711.  
  712.     pptr = Palette + (int)color * 3;
  713.  
  714.     prgb[0] = (pptr[0] * max_value) / 1000;
  715.     prgb[1] = (pptr[1] * max_value) / 1000;
  716.     prgb[2] = (pptr[2] * max_value) / 1000;
  717.  
  718.     return 0;
  719. }
  720.  
  721. /* Copy an image from Ghostscript's format to standard color planes. */
  722.  
  723. int
  724. stvdi_pack_to_plane(void)
  725. {
  726.     int i, plane_size;
  727.  
  728.     words = height * word_width - 1;    /* pixels/16 - 1 */
  729.     plane_size = 2 * word_width * height;
  730.  
  731.     /* Plane[i] holds the address of the ith color plane. */
  732.  
  733.     for (i=0; i<ColorBits; i++) {
  734.         plane[i] = (ushort *)(cbase + i * plane_size);
  735.     }
  736.  
  737.     /* Jump to the appropriate assembler image transformation. */
  738.  
  739.     switch (ColorBits) {
  740.  
  741.     case 2:        /* Two bit color. */
  742.         trans_2();
  743.         break;
  744.  
  745.     case 4:        /* Four bit color. */
  746.         trans_4();
  747.         break;
  748.  
  749.     case 8:        /* Eight bit color. */
  750.         trans_8();
  751.         break;
  752.  
  753.     case 16:    /* 16-bit color. */
  754.         trans_16();
  755.         break;
  756.  
  757.     }
  758.  
  759.     return (0);
  760. }
  761.  
  762. /* This routine is necessary because the vdi color indices are not
  763.  * the same as the color register numbers used by the hardware.
  764.  * It figures out the color register number associated with each
  765.  * color index by writing each color index to the screen and then
  766.  * examining which color register was used.
  767.  */
  768.  
  769. int reg_to_index(int *index_array, int c_bits, int p_size)
  770. {
  771.     unsigned short *wp;
  772.  
  773.     int i, index, creg, xy_pos[2], xy_size[8];
  774.  
  775.     long tpixel[8], plane[8];
  776.  
  777.     MFDB temp, screen, planes;
  778.  
  779.     screen.fd_addr   = (long)NULL;
  780.  
  781.     /* Temporary storage for for 16 screen pixels. */
  782.  
  783.     temp.fd_addr    = (long)tpixel;
  784.     temp.fd_w       = 16;
  785.     temp.fd_h       = 1;
  786.     temp.fd_wdwidth = 1;
  787.     temp.fd_stand   = 0;
  788.     temp.fd_nplanes = c_bits;
  789.  
  790.     /* 16 screen pixels in plane format. */
  791.  
  792.     planes.fd_addr    = (long)plane;
  793.     planes.fd_w       = 16;
  794.     planes.fd_h       = 1;
  795.     planes.fd_wdwidth = 1;
  796.     planes.fd_stand   = 0;
  797.     planes.fd_nplanes = c_bits;
  798.  
  799.     /* Screen position to write pixel. */
  800.  
  801.     xy_pos[0] = 0;
  802.     xy_pos[1] = 0;
  803.  
  804.     /* Size of screen image to copy. */
  805.  
  806.     xy_size[0] = 0;
  807.     xy_size[1] = 0;
  808.     xy_size[2] = 15;
  809.     xy_size[3] = 0;
  810.     xy_size[4] = xy_size[0];
  811.     xy_size[5] = xy_size[1];
  812.     xy_size[6] = xy_size[2];
  813.     xy_size[7] = xy_size[3];
  814.  
  815.     vswr_mode(VdiHandle, 1);    /* overwrite mode    */
  816.     vsm_type(VdiHandle, 1);    /* marker type "dot" */
  817.  
  818.     for (index=0; p_size--; index++) {
  819.         wp = (short int *)plane;
  820.  
  821.         vsm_color(VdiHandle, index);    /* set pixel color */
  822.         v_pmarker(VdiHandle, 1, xy_pos);    /* write pixel to screen */
  823.  
  824.         /* Copy pixel into temporary storage (transforming directly
  825.          * from the screen doesn't work on my machine).
  826.          */
  827.  
  828.         vro_cpyfm(VdiHandle, 3, xy_size, &screen, &temp);    
  829.  
  830.         /* Transform the screen image into color plane format. */
  831.  
  832.         vr_trnfm(VdiHandle, &temp, &planes);
  833.  
  834.         /* Convert the color plane information into a register number. */
  835.  
  836.         creg = 0;
  837.  
  838.         for (i=1; i<=c_bits; wp++, i++) {
  839.         if (*wp & 0x8000) {
  840.             creg += (1 << (i-1));
  841.         }
  842.         }
  843.  
  844. /*        index_array[creg] = index; */
  845.         index_array[index] = creg;
  846.  
  847.     }
  848.  
  849. }
  850.  
  851. __asm__("
  852.  
  853. .globl    _trans_2, _trans_4, _trans_8, _trans_16
  854.  
  855. _trans_2:
  856.  
  857.     |    a0      address of plane 0
  858.     |    a1      address of plane 1
  859.     |    a4      address of source pixels
  860.     |    d7      #pixels/16 - 1
  861.  
  862.     moveml    a0-a5/d0-d7, sp@-    | save the registers
  863.  
  864.     movel    _plane,   a0
  865.     movel    _plane+4, a1
  866.     movel    _tbase,   a4
  867.     movel    _words,   d7
  868.  
  869.     next_block2:
  870.     moveq  #1, d6            | 2 words for 16 pixels
  871.  
  872.     next_word2:
  873.     movew    a4@+, d4        | get 8 pixels
  874.     moveq    #7,   d5        | 8 pixels/word
  875.  
  876.     next_pixel2:
  877.     addw    d4, d4            | scatter pixels to 2 planes
  878.     addxw    d0, d0
  879.     addw    d4, d4
  880.     addxw    d1, d1
  881.  
  882.     dbra    d5, next_pixel2
  883.  
  884.     dbra    d6, next_word2
  885.  
  886.     movew    d0, a1@+        | store 1 word of each bit plane
  887.     movew    d1, a0@+
  888.  
  889.     subql    #1, d7
  890.     bpl    next_block2
  891.  
  892.     moveml    sp@+, a0-a5/d0-d7    | restore the registers
  893.     rts    
  894.  
  895.  
  896. _trans_4:
  897.  
  898.     |    a0      address of plane 0
  899.     |    a1      address of plane 1
  900.     |    a2      address of plane 2
  901.     |    a3      address of plane 3
  902.     |    a4      address of source pixels
  903.     |    d7      #pixels/16 - 1
  904.  
  905.     moveml    d0-d7/a0-a5, sp@-    | save registers
  906.  
  907.     movel    _plane,    a0
  908.     movel    _plane+4,  a1
  909.     movel    _plane+8,  a2
  910.     movel    _plane+12, a3
  911.     movel    _tbase,    a4
  912.     movel    _words, d7
  913.  
  914.     next_block4:
  915.     moveq  #3,d6            | 4 words for 16 pixels
  916.  
  917.     next_word4:
  918.     movew  a4@+,d4            | get 4 pixels
  919.     moveq  #3,d5            | 4 pixels/word
  920.  
  921.     next_pixel4:
  922.     addw   d4,d4            | scatter pixels to four planes
  923.     addxw  d0,d0
  924.     addw   d4,d4
  925.     addxw  d1,d1
  926.     addw   d4,d4
  927.     addxw  d2,d2
  928.     addw   d4,d4
  929.     addxw  d3,d3
  930.  
  931.     dbra   d5,next_pixel4
  932.  
  933.     dbra   d6,next_word4
  934.  
  935.     movew  d0,a3@+            | store 1 word of each bit plane
  936.     movew  d1,a2@+
  937.     movew  d2,a1@+
  938.     movew  d3,a0@+
  939.  
  940.     subql  #1,d7
  941.     bpl    next_block4
  942.  
  943.     moveml    sp@+, d0-d7/a0-a5    | restore registers
  944.     rts
  945.  
  946. _trans_8:
  947.  
  948.     |    a0      address of planes 0 & 4
  949.     |    a1      address of planes 1 & 5
  950.     |    a2      address of planes 2 & 6
  951.     |    a3      address of planes 3 & 7
  952.     |    a4      address of source pixels
  953.     |    a5    pointer to array containing addresses of color planes
  954.     |    d7      #pixels/16 - 1
  955.  
  956.     moveml    d0-d7/a0-a5, sp@-    | save registers
  957.  
  958.     movel    _tbase,    a4
  959.     movel    #_plane,   a5
  960.     movel    _words, d7
  961.  
  962.     pass_one8:            | first pass through the image
  963.     moveml    a5@(16), a0-a3    | get addresses of second 4 planes
  964.  
  965.     next_block8:
  966.     moveq    #7, d6        | 8 words for 16 pixels
  967.  
  968.     next_word8:
  969.     movew    a4@+, d4    | get 2 pixels
  970.  
  971.      addw    d4, d4        | scatter to first 4 planes
  972.     addxw    d0, d0
  973.     addw    d4, d4
  974.     addxw    d1, d1
  975.     addw    d4, d4
  976.     addxw    d2, d2
  977.     addw    d4, d4
  978.     addxw    d3, d3
  979.     rolw    #4, d4
  980.     addw    d4, d4
  981.     addxw    d0, d0
  982.     addw    d4, d4
  983.     addxw    d1, d1
  984.     addw    d4, d4
  985.     addxw    d2, d2
  986.     addw    d4, d4
  987.     addxw    d3, d3
  988.  
  989.     dbra    d6, next_word8
  990.  
  991.     movew    d0, a3@+    | store 1 word of each bit plane
  992.     movew    d1, a2@+
  993.         movew    d2, a1@+
  994.         movew    d3, a0@+
  995.  
  996.     subql    #1, d7
  997.     bpl    next_block8
  998.  
  999.     pass_two8:            | second pass through the image
  1000.     moveml    a5@, a0-a3    | get addresses of first 4 planes
  1001.     movel    _words, d7    | get #pixels/16 - 1
  1002.     movel    _tbase, a4    | get address of source pixels
  1003.  
  1004.     next_block8_2:
  1005.     moveq    #7, d6        | 8 words for 16 pixels
  1006.  
  1007.     next_word8_2:
  1008.     movew    a4@+, d4    | get 2 pixels
  1009.     rolw    #4, d4
  1010.  
  1011.      addw    d4, d4        | scatter to last 4 planes
  1012.     addxw    d0, d0
  1013.     addw    d4, d4
  1014.     addxw    d1, d1
  1015.     addw    d4, d4
  1016.     addxw    d2, d2
  1017.     addw    d4, d4
  1018.     addxw    d3, d3
  1019.     rolw    #4, d4
  1020.     addw    d4, d4
  1021.     addxw    d0, d0
  1022.     addw    d4, d4
  1023.     addxw    d1, d1
  1024.     addw    d4, d4
  1025.     addxw    d2, d2
  1026.     addw    d4, d4
  1027.     addxw    d3, d3
  1028.  
  1029.     dbra    d6, next_word8_2
  1030.  
  1031.         movew    d0, a3@+    | store 1 word of each bit plane
  1032.         movew    d1, a2@+
  1033.         movew    d2, a1@+
  1034.         movew    d3, a0@+
  1035.  
  1036.     subql  #1,d7
  1037.     bpl    next_block8_2
  1038.  
  1039.     moveml    sp@+, d0-d7/a0-a5    | restore registers
  1040.     rts
  1041.  
  1042.  
  1043. _trans_16:
  1044.  
  1045.     |    a0      address of planes 0, 4,  8, & 12
  1046.     |    a1      address of planes 1, 5,  9, & 13
  1047.     |    a2      address of planes 2, 6, 10, & 14
  1048.     |    a3      address of planes 3, 7, 11, & 15
  1049.     |    a4      address of source pixels
  1050.     |    a5    pointer to array containing addresses of color planes
  1051.     |    d7      #pixels/16 - 1
  1052.  
  1053.     moveml    d0-d7/a0-a5, sp@-    | save registers
  1054.  
  1055.     movel    _tbase,    a4
  1056.     movel    #_plane,   a5
  1057.     movel    _words, d7
  1058.  
  1059.     pass_one16:            | first pass through the image
  1060.     moveml    a5@(48), a0-a3    | get addresses of last 4 planes
  1061.  
  1062.     next_block16:
  1063.     moveq    #15, d6        | 16 words for 16 pixels
  1064.  
  1065.     next_word16:
  1066.     movew    a4@+, d4    | get 1 pixel
  1067.  
  1068.      addw    d4, d4        | scatter to first 4 planes
  1069.     addxw    d0, d0
  1070.     addw    d4, d4
  1071.     addxw    d1, d1
  1072.     addw    d4, d4
  1073.     addxw    d2, d2
  1074.     addw    d4, d4
  1075.     addxw    d3, d3
  1076.  
  1077.     dbra    d6, next_word16
  1078.  
  1079.         movew    d0, a3@+    | store 1 word of each bit plane
  1080.     movew    d1, a2@+
  1081.     movew    d2, a1@+
  1082.     movew    d3, a0@+
  1083.  
  1084.     subql    #1, d7
  1085.     bpl    next_block16
  1086.  
  1087.     pass_two16:            | second pass through the image
  1088.     moveml    a5@(32), a0-a3    | get addresses of next 4 planes
  1089.     movel    _words, d7    | get #pixels/16 - 1
  1090.     movel    _tbase, a4    | get address of source pixels
  1091.  
  1092.     next_block16_2:
  1093.     moveq    #15, d6        | 16 words for 16 pixels
  1094.  
  1095.     next_word16_2:
  1096.     movew    a4@+, d4    | get 1 pixel
  1097.     rolw    #4, d4
  1098.  
  1099.      addw    d4, d4        | scatter to last 4 planes
  1100.     addxw    d0, d0
  1101.     addw    d4, d4
  1102.     addxw    d1, d1
  1103.     addw    d4, d4
  1104.     addxw    d2, d2
  1105.     addw    d4, d4
  1106.     addxw    d3, d3
  1107.  
  1108.     dbra    d6, next_word16_2
  1109.  
  1110.         movew    d0, a3@+    | store 1 word of each bit plane
  1111.     movew    d1, a2@+
  1112.     movew    d2, a1@+
  1113.     movew    d3, a0@+
  1114.  
  1115.     subql  #1,d7
  1116.     bpl    next_block16_2
  1117.  
  1118.     pass_three16:            | third pass through the image
  1119.     moveml    a5@(16), a0-a3    | get addresses of next 4 planes
  1120.     movel    _words, d7    | get #pixels/16 - 1
  1121.     movel    _tbase, a4    | get address of source pixels
  1122.  
  1123.     next_block16_3:
  1124.     moveq    #15, d6        | 16 words for 16 pixels
  1125.  
  1126.     next_word16_3:
  1127.     movew    a4@+, d4    | get 1 pixel
  1128.     rolw    #8, d4
  1129.  
  1130.      addw    d4, d4        | scatter to last 4 planes
  1131.     addxw    d0, d0
  1132.     addw    d4, d4
  1133.     addxw    d1, d1
  1134.     addw    d4, d4
  1135.     addxw    d2, d2
  1136.     addw    d4, d4
  1137.     addxw    d3, d3
  1138.  
  1139.     dbra    d6, next_word16_3
  1140.  
  1141.     movew    d0, a3@+    | store 1 word of each bit plane
  1142.     movew    d1, a2@+
  1143.     movew    d2, a1@+
  1144.     movew    d3, a0@+
  1145.  
  1146.     subql  #1,d7
  1147.     bpl    next_block16_3
  1148.  
  1149.     pass_four16:            | fourth pass through the image
  1150.     moveml    a5@, a0-a3    | get addresses of first 4 planes
  1151.     movel    _words, d7    | get #pixels/16 - 1
  1152.     movel    _tbase, a4    | get address of source pixels
  1153.  
  1154.     next_block16_4:
  1155.     moveq    #15, d6        | 16 words for 16 pixels
  1156.  
  1157.     next_word16_4:
  1158.     movew    a4@+, d4    | get 1 pixel
  1159.     rorw    #4, d4
  1160.  
  1161.      addw    d4, d4        | scatter to last 4 planes
  1162.     addxw    d0, d0
  1163.     addw    d4, d4
  1164.     addxw    d1, d1
  1165.     addw    d4, d4
  1166.     addxw    d2, d2
  1167.     addw    d4, d4
  1168.     addxw    d3, d3
  1169.  
  1170.     dbra    d6, next_word16_4
  1171.  
  1172.     movew    d0, a3@+    | store 1 word of each bit plane
  1173.     movew    d1, a2@+
  1174.     movew    d2, a1@+
  1175.     movew    d3, a0@+
  1176.  
  1177.     subql  #1,d7
  1178.     bpl    next_block16_4
  1179.  
  1180.     moveml    sp@+, d0-d7/a0-a5    | restore registers
  1181.     rts
  1182.  
  1183. ");
  1184.